GAN with Keras
# Tag:
GAN with Keras
데이터 전처리
# Keras 2.9.0 from keras.models import Model, Sequential from keras.layers import Dense, Input from keras.layers import LeakyReLU from keras.optimizers import Adam from keras.datasets import mnist from tqdm import tqdm scaler = MinMaxScaler(feature_range=(-1, 1)) (x_train, y_train), (x_test, y_test) = mnist.load_data() x_test = x_test.astype(np.float32) mnist_data = (x_test- 127.5)/127.5 # => -1 ~ 1 # mnist_data = scaler.fit_transform(x_test)
- LeakyReLU: Activation Function
- tqdm: 모델 학습을 시각적으로 보여주는 라이브러리
ANN 모델 설계
Generator
def create_generator(): generator = Sequential() generator.add(Dense(units=256,input_dim=100)) generator.add(LeakyReLU(0.2)) # 음수 부분의 기울기 0.2 generator.add(Dense(units=512)) generator.add(LeakyReLU(0.2)) generator.add(Dense(units=784, activation='tanh')) # 28 x 28 = 784 return generator g = create_generator()
- input_dim: 100개의 픽셀, 노이즈값. 100개의 픽셀값이 랜덤한 값을 가진다.
Discriminator
def create_discriminator(): discriminator = Sequential() discriminator.add(Dense(units=512,input_dim=784)) #생성자의 출력 discriminator.add(LeakyReLU(0.2)) discriminator.add(Dense(units=256)) discriminator.add(LeakyReLU(0.2)) discriminator.add(Dense(units=1, activation='sigmoid')) # 0 or 1 discriminator.compile(loss='binary_crossentropy', optimizer = Adam(learning_rate=0.0002, beta_1=0.5)) return discriminator d = create_discriminator()
- binary_crossentropy: 이항 교차 엔트로피(Loss), 둘 중 하나로 분류하는 문제.
- (learning_rate, beta_1): (학습 속도(Weight의 이동 정도), 베타 최적화)
GAN
def create_gan(discriminator, generator): discriminator.trainable=False # 판별자의 학습을 막아둠. gan_input = Input(shape=(100,)) x = generator(gan_input) gan_output = discriminator(x) # 생성자가 만든 그림을 보고 판단한 결과 gan = Model(inputs=gan_input, outputs=gan_output) gan.compile(loss='binary_crossentropy', optimizer='adam') return gan gan = create_gan(d,g)
- Input(shape=): (데이터가 이루어진 값의 개수, 총 데이터의 개수), 총 데이터의 개수를 비워두면 실제 데이터의 개수가 자동으로 설정된다.
이미지 생성
def plot_generated_images(generator): noise = np.random.normal(loc=0, scale=1, size=[100, 100]) generated_images = generator.predict(noise) generated_images = generated_images.reshape(100,28,28) plt.figure(figsize=(10, 10)) # 그림 크기 설정 for i in range(generated_images.shape[0]): # 100번 반복 plt.subplot(10, 10, i+1) plt.imshow(generated_images[i], interpolation='nearest') plt.axis('off') plt.tight_layout()
- np.random.normal: loc(평균), scale(평균에서 떨어진 값: -1 ~ 1): 정규분
- subplot: (rows, cols, index)
- iterpolation='nearest': 각 픽셀을 어떻게 나타낼 지
학습
batch_size = 128 epochs = 5000 for e in tqdm(range(epochs)): noise = np.random.normal(0,1, [batch_size, 100]) generated_images = g.predict(noise) image_batch = mnist_data[np.random.randint(low=0, high=mnist_data.shape[0],size=batch_size)] #랜덤으로 그림을 추출. X = np.concatenate([image_batch, generated_images]) # 합치기 y_dis = np.zeros(2*batch_size) # 결과값, 전부 0. y_dis[:batch_size] = 1 # 앞의 128개는 실제 데이터이므로 1을 넣음. d.trainable = True d.train_on_batch(X, y_dis) # 학습, y_dis는 정답 데이터가 된다. noise = np.random.normal(0,1, [batch_size, 100]) # 입력 데이터 y_gen = np.ones(batch_size) # Generator의 입력이 진짜로 오해하게 함. d.trainable = False # 학습 중지, 판별만 함. gan.train_on_batch(noise, y_gen) if e == 0 or e % 1000 == 0: plot_generated_images(g)
- image_batch = mnist_data[np.random.randint(low=0,high=mnist_data.shape[0],size=batch_size)]: 실제 정답 데이터에서 랜덤하게 이미지를 가져옴.
- train_on_batch: 신경망의 데이터 학습. d.trainable = False 일 때는, D는 학습하지 않고 판별만 진행한다. y_gen과 출력값을 비교하면서, 판별 결과가 1이 나올때까지 생성자를 학습시킨다.